package sketch.skeleton;

import java.util.Arrays;
import java.util.Map;

import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.Statement;

import sketch.ast.ASTUtils;
import sketch.util.Checker;

public class SkeletonCreator {

	public static final String EXTEND_CLASS_NAME = "GenTest";
	
	public static final String OVERRIDEN_TEST_NAME = "scratchTest";
	
	public final String classFile;
	
	public SkeletonCreator(String classFile) {
		Checker.checkNull(classFile, "The class file input should not be null!");
		this.classFile = classFile;
	}
	
	/**
	 * Initialize an empty skeleton, and put Java source and generators to their right places
	 * */
	public Skeleton createSkeleton() {
		Skeleton skeleton = new Skeleton();
		
		//add import statements
		skeleton.addImports(ASTUtils.extractImportDeclarations(this.classFile));
		
		//set the java source
		Map<Integer, Statement> javaSources =
			ASTUtils.extractJavaStatements(this.classFile, EXTEND_CLASS_NAME, OVERRIDEN_TEST_NAME);
		
		//set the receiver object of generating statement
		Map<Integer, Expression> receiverObjs =
			ASTUtils.extractReceiverObjects(this.classFile, EXTEND_CLASS_NAME, OVERRIDEN_TEST_NAME);
		
		//int statementSize = javaSources.size() + receiverObjs.size();
		
		Integer[] javaSourceIndices = (Integer[])(javaSources.keySet().toArray(new Integer[0]));
		Arrays.sort(javaSourceIndices);
		
		for(int i : javaSourceIndices) {
			System.out.println(i);
		}
		
		Integer[] receiverObjIndices = (Integer[])(receiverObjs.keySet().toArray(new Integer[0]));
		Arrays.sort(receiverObjIndices);
		
		for(int i : receiverObjIndices) {
			System.out.println(i);
		}
		
		int javaSourceIndex = 0;
		int receiverObjIndex = 0;
		int relativeGeneratedIndex = 0;
		
		while(javaSourceIndex < javaSourceIndices.length || receiverObjIndex < receiverObjIndices.length ) {
			if(javaSourceIndex == javaSourceIndices.length ) {
				while(receiverObjIndex < receiverObjIndices.length) {
				  SkeletonElement genSourceCode = new GeneratorSourceCode(relativeGeneratedIndex, receiverObjs.get(receiverObjIndices[receiverObjIndex]));
				  skeleton.addElement(genSourceCode);
				  skeleton.setGeneratedHoles(relativeGeneratedIndex, genSourceCode);
				  relativeGeneratedIndex++;
				  receiverObjIndex++;
				}
			} else if(receiverObjIndex == receiverObjIndices.length ) {
				while(javaSourceIndex < javaSourceIndices.length) {
					SkeletonElement sourceCode = new JavaSourceCode(javaSources.get(javaSourceIndices[javaSourceIndex]).toString());
					javaSourceIndex ++;
					skeleton.addElement(sourceCode);
				}
			} else {
				int sourceIndexStrPos = javaSourceIndices[javaSourceIndex];
				int receiverObjStrPos = receiverObjIndices[receiverObjIndex];
				if (sourceIndexStrPos < receiverObjStrPos) {
					SkeletonElement sourceCode = new JavaSourceCode(javaSources.get(sourceIndexStrPos).toString());
					javaSourceIndex ++;
					skeleton.addElement(sourceCode);
				} else if( sourceIndexStrPos > receiverObjStrPos) {
					SkeletonElement genSourceCode = new GeneratorSourceCode(relativeGeneratedIndex, receiverObjs.get(receiverObjStrPos));
					skeleton.addElement(genSourceCode);
					skeleton.setGeneratedHoles(relativeGeneratedIndex, genSourceCode);
					relativeGeneratedIndex++;
					receiverObjIndex++;
				} else {
					throw new RuntimeException("can not be equal: " + sourceIndexStrPos);
				}
			}
			
		}
		
		return skeleton;
	}
	
	/**
	 * A simple testing driver
	 * */
	public static void main(String[] args) {
		String filePath = "/scratch/eclipseworkspace/SketchSeq/examples/TreeMapSketchExecution.java";
		SkeletonCreator creator = new SkeletonCreator(filePath);
		Skeleton skeleton = creator.createSkeleton();
		System.out.println(skeleton.toCodeString());
	}
}